﻿using PublicEntity;
using SocketServer.Model;
using SocketServer.SocketAttribute;
using SocketServer.WebSocketAction;
using System;
using System.Collections.Generic;
using System.Linq;
/*
 * 说    明：程序使用的NuGet插件
 *              Fleck(1.2.0.0)
 *              Newtonsoft.Json(13.0.0.0)
 *           程序使用的自定义实体
 *              PublicEntity
 */
namespace SocketServer
{
    /// <summary>
    /// 帮助实现 MessageEvent 、OnMessageBytesEvent、CloseEvent、OpenEvent 的默认事件
    /// 在使用这个类时，会导致(MessageEvent 、OnMessageBytesEvent)事件失效
    /// </summary>
    /// <remarks>
    /// 注意:在使用byte[]方式进行通讯时,请先看PublicEntity.SocketByteReceive、PublicEntity.SocketByteReceive类
    /// </remarks>
    public class WebSocketServerStartHelper : WebSocketServerHelper
    {
        /// <summary>
        /// 实例化
        /// </summary>
        /// <param name="url">链接 示例:"ws://127.0.0.1:8888"</param>
        /// <param name="DefaultClass">Socket默认class</param>
        /// <param name="ClassConvert">指示字符串如何转换为类(默认Newtonsoft.Json.JsonConvert.DeserializeObject)</param>
        public WebSocketServerStartHelper(string url, string DefaultClass = null, Func<string, Type, object> ClassConvert = null) : base(url)
        {
            this.DefaultClass = DefaultClass;
            this.Assemblys = new List<System.Reflection.Assembly>();
            this.Types = new List<Type>();
            this.IWebSocketList = new List<KeyValuePair<string, IWebSocketServerAction>>();
            this.ClassConvert = ClassConvert ?? Newtonsoft.Json.JsonConvert.DeserializeObject;
            this.SkipStringList = new List<string>
            {
                "null", string.Empty
            };
        }

        /// <summary>
        /// 加载程序集
        /// </summary>
        /// <param name="assemblies">程序集数组</param>
        /// <remarks>
        /// System.Reflection.Assembly.GetExecutingAssembly()
        /// 获取当前程序的Assembly
        /// </remarks>
        /// <returns></returns>
        public WebSocketServerStartHelper SetAssemblies(params System.Reflection.Assembly[] assemblies)
        {
            this.Assemblys.AddRange(assemblies);
            return this;
        }

        /// <summary>
        /// 加载Type
        /// </summary>
        /// <param name="Types">Type数组</param>
        /// <returns></returns>
        public WebSocketServerStartHelper SetTypes(params Type[] Types)
        {
            this.Types.AddRange(Types);
            return this;
        }

        /// <summary>
        /// 加载Type
        /// </summary>
        /// <typeparam name="T">加载的类型</typeparam>
        /// <returns></returns>
        public WebSocketServerStartHelper SetType<T>()
        {
            this.Types.Add(typeof(T));
            return this;
        }

        /// <summary>
        /// 获取当前实体中存在的Socket服务类
        /// </summary>
        /// <typeparam name="ClassT">Socket服务类的Type</typeparam>
        /// <returns>null表示服务端未启动或不存在</returns>
        public ClassT GetClass<ClassT>()
            where ClassT : class, IWebSocketServerAction
        {
            var obj = GetClass(typeof(ClassT));
            if (obj == null)
            {
                return null;
            }
            return obj as ClassT;
        }

        /// <summary>
        /// 获取当前实体中存在的Socket服务类
        /// </summary>
        /// <param name="type">Socket服务类的Type</param>
        /// <returns>null表示服务端未启动或不存在</returns>
        public IWebSocketServerAction GetClass(Type type)
        {
            var keyValue = IWebSocketList.FirstOrDefault(t => t.Key.Equals(type.Name));
            return keyValue.Value;
        }

        /// <summary>
        /// 获取当前实体中所有的Socket服务类
        /// </summary>
        /// <returns>null表示服务端未启动或不存在</returns>
        public IEnumerable<IWebSocketServerAction> GetClassAll()
        {
            return IWebSocketList.Select(t => t.Value);
        }

        #region 后期绑定特性的方法
        /// <summary>
        /// 后期绑定特性的方法(需要在首次调用Start后调用)
        /// </summary>
        /// <typeparam name="ClassT">绑定特性的类型</typeparam>
        /// <typeparam name="AttributeT">后期绑定的特性</typeparam>
        /// <param name="IsDistinct">是否去除相同特性</param>
        /// <remarks>
        /// 直接对 IWebSocketList 的 FilterList 属性设置也是一样的
        /// </remarks>
        /// <returns>是否成功设置</returns>
        public bool SetAttribute<ClassT, AttributeT>(bool IsDistinct = true)
            where ClassT : IWebSocketServerAction
            where AttributeT : WebSocketFilterAttribute, new()
        {
            return SetAttribute(typeof(ClassT), typeof(AttributeT), IsDistinct);
        }

        /// <summary>
        /// 后期绑定特性的方法(需要在首次调用Start后调用)
        /// </summary>
        /// <param name="classType">绑定特性的类型</param>
        /// <param name="attributeType">后期绑定的特性</param>
        /// <param name="IsDistinct">是否去除相同特性</param>
        /// <remarks>
        /// 直接对 IWebSocketList 的 FilterList 属性设置也是一样的
        /// </remarks>
        /// <returns>是否成功设置</returns>
        public bool SetAttribute(Type classType, Type attributeType, bool IsDistinct = true)
        {
            var SocketServer = GetClass(classType);
            if (SocketServer == null)
            {
                return false;
            }
            if (IsDistinct && SocketServer.FilterList.FirstOrDefault(t => t.GetType().Equals(attributeType)) != null)
            {
                return false;
            }
            try
            {
                var att = attributeType.Assembly.CreateInstance(attributeType.FullName) as WebSocketFilterAttribute;
                if (att == null)
                {
                    return false;
                }
                SocketServer.FilterList.Add(att);
                return true;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 后期绑定特性的方法(需要在首次调用Start后调用)
        /// </summary>
        /// <param name="Dic">Key=绑定特性的类型字符串(Type.Name),Value=需要绑定的特性(Type.FullName)</param>
        /// <param name="IsDistinct">是否去除相同特性</param>
        /// <remarks>
        /// 直接对 IWebSocketList 的 FilterList 属性设置也是一样的
        /// </remarks>
        public void SetAttribute(Dictionary<string, List<string>> Dic, bool IsDistinct = true)
        {
            //System.Reflection.Assembly.Load(classType.FullName);
            //Activator.CreateInstance();
            foreach (var keyValue in Dic)
            {
                var SocketServer = IWebSocketList.FirstOrDefault(t => t.Key.Equals(keyValue.Key)).Value;
                if (SocketServer == null)
                {
                    continue;
                }
                var _groupBy = keyValue.Value.GroupBy(t =>
                {
                    var index = t.IndexOf('.');
                    if (index < 0)
                    {
                        return t;
                    }
                    return t.Substring(0, index);
                }, t => t);
                foreach (var groupBy in _groupBy)
                {
                    System.Reflection.Assembly assembly = null;
                    try
                    {
                        assembly = System.Reflection.Assembly.Load(groupBy.Key);
                    }
                    catch (Exception)
                    {
                        continue;
                    }
                    foreach (var item in groupBy)
                    {
                        var type = assembly.GetType(item);
                        if (type == null)
                        {
                            continue;
                        }
                        if (IsDistinct && SocketServer.FilterList.FirstOrDefault(t => t.GetType().Equals(type)) != null)
                        {
                            continue;
                        }
                        var att = assembly.CreateInstance(type.FullName) as WebSocketFilterAttribute;
                        if (att != null)
                        {
                            SocketServer.FilterList.Add(att);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 后期绑定特性的方法 - 对所有的类都进行绑定(需要在首次调用Start后调用)
        /// </summary>
        /// <param name="AttributeList">需要绑定的特性(Type.FullName)</param>
        /// <param name="SkipList">指示哪些类跳过绑定</param>
        /// <param name="IsDistinct">是否去除相同特性</param>
        /// <remarks>
        /// 直接对 IWebSocketList 的 FilterList 属性设置也是一样的
        /// </remarks>
        public void SetAttribute(List<string> AttributeList, List<string> SkipList = null, bool IsDistinct = true)
        {
            //System.Reflection.Assembly.Load(classType.FullName);
            //Activator.CreateInstance();
            var _AttributeList = AttributeList.
                GroupBy(t =>
                {
                    var index = t.IndexOf('.');
                    if (index < 0)
                    {
                        return t;
                    }
                    return t.Substring(0, index);
                }, t => t).
                Select(t =>
                {
                    try
                    {
                        var assembly = System.Reflection.Assembly.Load(t.Key);
                        if (assembly == null)
                        {
                            return null;
                        }
                        return t.Select(tt =>
                        {
                            var _type = assembly.GetType(tt);
                            if (_type == null)
                            {
                                return null;
                            }
                            return assembly.CreateInstance(_type.FullName) as WebSocketFilterAttribute;
                        }).Where(tt => tt != null).ToList();
                    }
                    catch
                    {
                        return null;
                    }
                }).
                Where(t => t != null).
                ToList();
            if (_AttributeList.Count < 1)
            {
                return;
            }
            foreach (var keyValue in IWebSocketList)
            {
                if (SkipList != null && SkipList.Contains(keyValue.Key))
                {
                    continue;
                }
                var SocketServer = keyValue.Value;
                foreach (var item in _AttributeList)
                {
                    if (!IsDistinct)
                    {
                        SocketServer.FilterList.AddRange(item);
                        continue;
                    }
                    SocketServer.FilterList.AddRange(item.Where(t => SocketServer.FilterList.FirstOrDefault(tt => tt.GetType().Equals(t.GetType())) == null));
                }
            }
        }
        #endregion

        /// <summary>
        /// 对所有缓存客户端广播消息(无论在哪个实体缓存都会广播到,如果对多个实体缓存则会广播多次)
        /// </summary>
        /// <param name="Bol">是否成功</param>
        /// <param name="Status">状态</param>
        /// <param name="Message">消息</param>
        /// <param name="Data">数据</param>
        public void BroadcastMessage(bool Bol, int Status, string Message, object Data)
        {
            ResponseResult responseResult = new ResponseResult(Bol)
            {
                Message = Message,
                Data = Data,
                Status = Status
            };
            foreach (var SocketServer in IWebSocketList)
            {
                SocketServer.Value.BroadcastMessage(responseResult);
            }
        }

        #region 属性字段
        /// <summary>
        /// 遇到集合中的字符串会替换为默认值
        /// </summary>
        /// <remarks>
        /// 默认值"null",""
        /// </remarks>
        public List<string> SkipStringList { get; private set; }

        /// <summary>
        /// 反射加载的程序集
        /// </summary>
        private List<System.Reflection.Assembly> Assemblys { get; }

        /// <summary>
        /// 反射加载的程序集
        /// </summary>
        private List<Type> Types { get; }

        /// <summary>
        /// 权限过滤器Type
        /// </summary>
        private static readonly Type typeAuthorizeAttribute = typeof(SocketAttribute.WebSocketFilterAttribute);

        /// <summary>
        /// 返回值Type
        /// </summary>
        private static readonly Type typeResult = typeof(SocketResult.ISocketResult);
        /// <summary>
        /// 实现了Socket方法的类
        /// </summary>
        private static readonly Type iServerActionType = typeof(IWebSocketServerAction);
        /// <summary>
        /// Socket默认class
        /// </summary>
        public string DefaultClass { get; }

        /// <summary>
        /// WebSocket的链接集合
        /// </summary>
        private List<KeyValuePair<string, WebSocketAction.IWebSocketServerAction>> IWebSocketList { get; }

        /// <summary>
        /// 是否添加一个方法都没有的类
        /// </summary>
        public bool IsAddNoMethod { get; set; }

        /// <summary>
        /// 字符编码(用于解析OnMessageBytesEvent方法的byte[])
        /// </summary>
        public System.Text.Encoding encoding = System.Text.Encoding.UTF8;

        /// <summary>
        /// 指示字符串如何转换为类(建议使用Newtonsoft.Json.JsonConvert.DeserializeObject)
        /// </summary>
        public Func<string, Type, object> ClassConvert { get; set; }
        #endregion

        #region 异常处理相关
        /// <summary>
        /// 出现异常时事件
        /// 第一个参数:异常信息;
        /// 第二个参数:导致出现异常的参数;
        /// </summary>
        public event Action<Exception, SocketRequest> ErrorEvent;

        /// <summary>
        /// 触发异常处理事件(ErrorEvent)
        /// </summary>
        /// <param name="exception">异常信息</param>
        /// <param name="Request">客户端请求的相关参数</param>
        protected virtual void OnErrorEvent(Exception exception, SocketRequest Request)
        {
            if (ErrorEvent != null)
            {
                ErrorEvent(exception, Request);
            }
        }
        #endregion

        /// <summary>
        /// 开启服务
        /// </summary>
        public override void Start()
        {
            Load();
            base.Start();
        }

        #region 初始化相关
        /// <summary>
        /// 第一次加载时加载
        /// </summary>
        private void Load()
        {
            //第一次加载时加载
            if (IsSatrt)
            {
                return;
            }
            IWebSocketList.Clear();
            foreach (var assembly in Assemblys)
            {
                var types = assembly.GetTypes();
                LoadAction(types, assembly);
            }
            LoadAction(Types);
        }

        /// <summary>
        /// 反射加载Type
        /// </summary>
        /// <param name="typeArray">type数组</param>
        /// <param name="assembly">type的程序集</param>
        private void LoadAction(IEnumerable<Type> typeArray, System.Reflection.Assembly assembly = null)
        {
            foreach (var type in typeArray.Where(ClassFunc))
            {
                object t = null;
                if (assembly == null)
                {
                    t = type.Assembly.CreateInstance(type.FullName);
                }
                else
                {
                    t = assembly.CreateInstance(type.FullName);
                }
                var serverStartPublic = GetMethods(t as IWebSocketServerAction);
                if (serverStartPublic == null)
                {
                    continue;
                }
                if (serverStartPublic.MethodList == null)
                {
                    continue;
                }
                if (!IsAddNoMethod && serverStartPublic.MethodList.Count < 1)
                {
                    continue;
                }
                if (IWebSocketList.Count(tt => tt.Key == type.Name) > 0)
                {
                    continue;
                }
                serverStartPublic.FilterList = type.GetCustomAttributes(typeAuthorizeAttribute, false).
                        Select(tt => tt as SocketAttribute.WebSocketFilterAttribute).
                        Where(tt => tt != null).
                        ToList();
                var keyVal = new KeyValuePair<string, IWebSocketServerAction>(type.Name, serverStartPublic);
                serverStartPublic.SocketList = new List<Fleck.IWebSocketConnection>();
                serverStartPublic.CacheMaxCount = 100;
                IWebSocketList.Add(keyVal);
            }
        }

        /// <summary>
        /// 获取Socket方法的过滤逻辑
        /// </summary>
        /// <param name="type">校验的类型</param>
        /// <returns></returns>
        private bool ClassFunc(Type type)
        {
            if (!type.IsClass)
            {
                return false;
            }
            if (!type.IsPublic)
            {
                return false;
            }
            if (type.IsGenericType)
            {
                return false;
            }
            if (type.GetInterface(iServerActionType.FullName) == null)
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// 获取类里面的Socket方法
        /// </summary>
        /// <param name="serverStartPublic">获取方法的类型</param>
        /// <returns>将获取到的类原样返回,如果有方法则获取方法</returns>
        private IWebSocketServerAction GetMethods(IWebSocketServerAction serverStartPublic)
        {
            if (serverStartPublic == null)
            {
                return serverStartPublic;
            }
            Type typeT = serverStartPublic.GetType();
            serverStartPublic.MethodList = typeT.GetMethods().Where(MethodFunc).
                    Select(t => new Model.MethodHelper
                    {
                        Method = t,
                        Parameters = t.GetParameters(),
                        FilterList = t.GetCustomAttributes(typeAuthorizeAttribute, false).
                            Select(tt => tt as SocketAttribute.WebSocketFilterAttribute).
                            Where(tt => tt != null).
                            ToList(),
                    }).ToList();
            return serverStartPublic;
        }

        /// <summary>
        /// 获取Socket方法的过滤逻辑
        /// </summary>
        /// <param name="method">校验的方法</param>
        /// <returns></returns>
        private bool MethodFunc(System.Reflection.MethodInfo method)
        {
            if (!method.IsPublic)
            {
                return false;
            }
            if (method.IsGenericMethod)
            {
                return false;
            }
            if (method.ReturnType.FullName.Equals(typeResult.FullName))
            {
                return true;
            }
            if (method.ReturnType.GetInterface(typeResult.FullName) == null)
            {
                return false;
            }
            return true;
        }
        #endregion

        #region 接受到的客户端消息 进行处理
        /// <summary>
        /// 默认byte[]消息处理
        /// </summary>
        /// <param name="socket">客户端Socket</param>
        /// <param name="message">byte数组消息</param>
        /// <remarks>
        /// 请先看PublicEntity.SocketByteReceive、PublicEntity.SocketByteSend类
        /// </remarks>
        protected override void OnMessageBytesEvent(Fleck.IWebSocketConnection socket, byte[] message)
        {
            if (message == null || message.Length < 1)
            {
                socket.RError("参数不存在");
                return;
            }
            SocketByteReceive socketByteReceive = new SocketByteReceive(message, encoding);
            if (string.IsNullOrEmpty(socketByteReceive.ApiPath))
            {
                socket.RError("请求路径不存在");
                return;
            }
            var ApiPathClass = socketByteReceive.ApiPathClass ?? DefaultClass;
            var ApiPathAction = socketByteReceive.ApiPathAction;
            if (string.IsNullOrEmpty(ApiPathClass))
            {
                socket.RError("未指定默认路径");
                return;
            }

            IWebSocketServerAction IWebSocketClass = GetIWebSocketServerAction(ApiPathClass, socket);
            if (IWebSocketClass == null)
            {
                return;
            }
            var Request = GetSocketRequest(ApiPathAction, IWebSocketClass);
            if (Request == null)
            {
                socket.RError("未找到指定方法");
                return;
            }
            Request.Socket = socket;
            Request.ClassName = ApiPathClass;
            Request.ApiPath = socketByteReceive.ApiPath;
            Request.ByteMessage = message;
            try
            {
                socketByteReceive.StartAnalysis((ex, Name) =>
                {
                    socket.RError(string.Format("解析参数[{0}]异常:{1}", Name, ex.Message));
                    OnErrorEvent(ex, Request);
                });
            }
            catch (Exception ex)
            {
                socket.RError(string.Format("解析byte数组时异常:{0}", ex.Message));
                OnErrorEvent(ex, Request);
                return;
            }
            Request.Parameters = socketByteReceive.Parameters;
            Request.FileParameters = socketByteReceive.FileParameters;
            ExecuteServerAction(IWebSocketClass, Request);
        }

        /// <summary>
        /// 默认的消息处理
        /// </summary>
        /// <param name="socket">客户端</param>
        /// <param name="message">客户端发来的消息</param>
        protected override void OnMessage(Fleck.IWebSocketConnection socket, string message)
        {
            if (string.IsNullOrEmpty(message))
            {
                socket.RError("未传递路径");
                return;
            }
            //请求路径
            string ApiPath = string.Empty;
            //请求参数
            string ApiParameter = string.Empty;
            int index = message.IndexOf('?');
            if (index != -1)
            {
                ApiPath = message.Substring(0, index);
                ApiParameter = message.Substring(index + 1);
            }
            else
            {
                ApiPath = message;
                ApiParameter = "";
            }
            index = ApiPath.IndexOf('/');
            string ApiPathClass = DefaultClass;
            string ApiPathAction = ApiPath;
            if (index != -1)
            {
                ApiPathClass = ApiPath.Substring(0, index);
                ApiPathAction = ApiPath.Substring(index + 1);
            }
            if (string.IsNullOrEmpty(ApiPathClass))
            {
                socket.RError("未指定默认路径");
                return;
            }
            IWebSocketServerAction IWebSocketClass = GetIWebSocketServerAction(ApiPathClass, socket);

            if (IWebSocketClass == null)
            {
                return;
            }

            var Request = GetSocketRequest(ApiPathAction, IWebSocketClass);
            if (Request == null)
            {
                socket.RError("未找到指定方法");
                return;
            }

            if (!string.IsNullOrEmpty(ApiParameter))
            {
                Request.Parameters = new List<NameValue<string, string>>();
                foreach (var item in ApiParameter.Split('&'))
                {
                    if (string.IsNullOrEmpty(item))
                    {
                        continue;
                    }
                    index = -1;
                    index = item.IndexOf('=');
                    if (index == -1)
                    {
                        continue;
                    }
                    var value = item.Substring(index + 1);
                    if (SkipStringList.Contains(value))
                    {
                        continue;
                    }
                    var key = item.Substring(0, index);
                    Request.Parameters.Add(new NameValue<string, string> { Name = key, Value = value });
                }
            }
            Request.Socket = socket;
            Request.ClassName = ApiPathClass;
            Request.ApiPath = ApiPath;
            Request.StringMessage = message;
            ExecuteServerAction(IWebSocketClass, Request);
        }

        /// <summary>
        /// 执行服务端的方法
        /// </summary>
        /// <param name="IWebSocketClass"></param>
        /// <param name="Request">客户端请求相关参数</param>
        /// <returns></returns>
        private void ExecuteServerAction(IWebSocketServerAction IWebSocketClass, SocketRequest Request)
        {
            //缓存方法到这就结束了
            if (Request.Method == null)
            {
                Cache(IWebSocketClass, Request);
                return;
            }

            //克隆一个全新的对象
            var _IWebSocketClass = IWebSocketClass.Clone() as IWebSocketServerAction;
            _IWebSocketClass.Socket = Request.Socket;
            _IWebSocketClass.Request = Request;
            foreach (var item in WebSocketFilterAttribute.GetWebSocketFilterAttribute(_IWebSocketClass.FilterList, Request.Method.FilterList))
            {
                item.OnAuthorization(_IWebSocketClass);
                if (_IWebSocketClass.IsEnd)
                {
                    return;
                }
            }

            object[] objectArray = null;
            if (Request.Method.Parameters.Length > 0)
            {
                var parameters = Request.Method.Parameters;
                objectArray = new object[parameters.Length];
                for (int i = 0; i < parameters.Length; i++)
                {
                    var parameter = parameters[i];
                    string name = parameter.Name;

                    if (SocketFile.IsSocketFileType(parameter.ParameterType))
                    {
                        NameValue<string, SocketFile> model = null;
                        if (Request.FileParameters != null)
                        {
                            model = Request.FileParameters.FirstOrDefault(t => t.Name == name);
                        }
                        if (model == null)
                        {
                            objectArray[i] = null;
                        }
                        else
                        {
                            objectArray[i] = model.Value.Convert(parameter.ParameterType);
                        }
                        continue;
                    }
                    if (parameter.ParameterType.IsGenericType)
                    {
                        var type = parameter.ParameterType.GenericTypeArguments[0];
                        if (SocketFile.IsSocketFileType(type))
                        {
                            if (Request.FileParameters == null)
                            {
                                objectArray[i] = null;
                            }
                            else
                            {
                                var list = parameter.ParameterType.Assembly.CreateInstance(parameter.ParameterType.FullName) as System.Collections.IList;
                                foreach (var item in Request.FileParameters.Where(t => t.Name == name).Select(t => t.Value.Convert(type)))
                                {
                                    list.Add(item);
                                }
                                objectArray[i] = list;
                            }
                            continue;
                        }
                    }
                    if (parameter.ParameterType.IsArray)
                    {
                        var type = parameter.ParameterType.UnderlyingSystemType.Assembly.GetType(parameter.ParameterType.FullName.TrimEnd('[', ']'));

                        if (SocketFile.IsSocketFileType(type))
                        {
                            if (Request.FileParameters == null)
                            {
                                objectArray[i] = null;
                            }
                            else
                            {
                                var list = Array.CreateInstance(type, Request.FileParameters.Where(t => t.Name == name).Count());
                                int ii = 0;
                                foreach (var item in Request.FileParameters.Where(t => t.Name == name).Select(t => t.Value.Convert(type)))
                                {
                                    list.SetValue(item, ii++);
                                }
                                objectArray[i] = list;
                            }
                            continue;
                        }
                    }

                    var keyValue = Request.Parameters.FirstOrDefault(t => t.Name == name);
                    if (keyValue == null)
                    {
                        if (parameter.DefaultValue != DBNull.Value)
                        {
                            objectArray[i] = parameter.DefaultValue;
                        }
                        else
                        {
                            Request.RError(string.Format("参数[{0}]不存在", name));
                            return;
                        }
                        continue;
                    }
                    string FullName = parameter.ParameterType.FullName;
                    try
                    {
                        if (parameter.ParameterType.IsClass && !FullNameHelper.StringFullName.Equals(FullName))
                        {
                            if (ClassConvert != null)
                            {
                                objectArray[i] = ClassConvert(keyValue.Value, parameter.ParameterType);
                            }
                            else
                            {
                                objectArray[i] = null;
                            }
                        }
                        else
                        {
                            objectArray[i] = FullNameHelper.ObjectConvert(FullName, keyValue.Value);
                        }
                    }
                    catch (Exception)
                    {
                        Request.RError(string.Format("参数[{0}]转换失败,转换的值[{1}]", name, keyValue.Value));
                        return;
                    }
                }
            }
            object result = null;
            try
            {
                foreach (var item in WebSocketFilterAttribute.GetWebSocketFilterAttribute(_IWebSocketClass.FilterList, Request.Method.FilterList))
                {
                    item.OnActionExecuting(_IWebSocketClass);
                    if (_IWebSocketClass.IsEnd)
                    {
                        return;
                    }
                }

                //执行方法
                result = Request.Method.Method.Invoke(_IWebSocketClass, objectArray);

                foreach (var item in WebSocketFilterAttribute.GetWebSocketFilterAttribute(_IWebSocketClass.FilterList, Request.Method.FilterList))
                {
                    item.OnActionExecuted(_IWebSocketClass);
                    if (_IWebSocketClass.IsEnd)
                    {
                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null)
                {
                    ex = ex.InnerException;
                }
                Request.RError(string.Format("执行方法时异常:{0}", ex.Message));
                OnErrorEvent(ex, Request);
                _IWebSocketClass.ExceptionResult = ex;
                foreach (var item in WebSocketFilterAttribute.GetWebSocketFilterAttribute(_IWebSocketClass.FilterList, Request.Method.FilterList))
                {
                    item.OnExceptionExecuting(_IWebSocketClass);
                    if (_IWebSocketClass.IsEnd)
                    {
                        return;
                    }
                }
                return;
            }
            var SocketResult = result as SocketResult.ISocketResult;
            _IWebSocketClass.Result = SocketResult == null ? null : SocketResult.GetData();
            foreach (var item in WebSocketFilterAttribute.GetWebSocketFilterAttribute(_IWebSocketClass.FilterList, Request.Method.FilterList))
            {
                item.OnResultExecuting(_IWebSocketClass);
                if (_IWebSocketClass.IsEnd)
                {
                    return;
                }
            }

            SendResult(Request.Socket, SocketResult);

            foreach (var item in WebSocketFilterAttribute.GetWebSocketFilterAttribute(_IWebSocketClass.FilterList, Request.Method.FilterList))
            {
                item.OnResultExecuted(_IWebSocketClass);
                if (_IWebSocketClass.IsEnd)
                {
                    return;
                }
            }
        }

        /// <summary>
        /// 通过类路径获取IWebSocketServerAction
        /// </summary>
        /// <param name="ApiPathClass">类路径</param>
        /// <param name="socket">如果不为空的时,在找不到IWebSocketServerAction时会给客户端提示</param>
        /// <returns></returns>
        private IWebSocketServerAction GetIWebSocketServerAction(string ApiPathClass, Fleck.IWebSocketConnection socket = null)
        {
            IWebSocketServerAction IWebSocketClass = null;
            foreach (var item in IWebSocketList)
            {
                if (item.Key == ApiPathClass)
                {
                    IWebSocketClass = item.Value;
                    break;
                }
            }
            if (IWebSocketClass == null && socket != null)
            {
                socket.RError("未找到指定类");
                return IWebSocketClass;
            }
            return IWebSocketClass;
        }

        /// <summary>
        /// 获取请求的部分参数(Method,ActionName)
        /// </summary>
        /// <param name="ApiPathAction">请求的Api方法</param>
        /// <param name="IWebSocketClass">请求的类</param>
        /// <returns>null表示未找到方法</returns>
        private SocketRequest GetSocketRequest(string ApiPathAction, IWebSocketServerAction IWebSocketClass)
        {
            Model.MethodHelper methodHelper = null;
            //如果是缓存方法则跳过检查方法步骤
            if (!ApiPathAction.Equals(CacheName))
            {
                methodHelper = IWebSocketClass.MethodList.FirstOrDefault(t => t.Method.Name.Equals(ApiPathAction));
                if (methodHelper == null)
                {
                    return null;
                }
            }
            SocketRequest Request = new SocketRequest();
            Request.ActionName = ApiPathAction;
            Request.Method = methodHelper;
            return Request;
        }

        /// <summary>
        /// 对客户端发送结果
        /// </summary>
        /// <param name="socket">客户端</param>
        /// <param name="SocketResult">继承了 ISocketResult 的类</param>
        private void SendResult(Fleck.IWebSocketConnection socket, SocketResult.ISocketResult SocketResult)
        {
            if (SocketResult == null)
            {
                return;
            }
            SocketResult.SendResult(socket);
        }

        /// <summary>
        /// 缓存的方法名
        /// </summary>
        private const string CacheName = "Cache";

        /// <summary>
        /// 将当前请求的socket客户端缓存起来
        /// </summary>
        /// <param name="IWebSocketClass">请求到的类</param>
        /// <param name="Request">客户端请求的参数</param>
        /// <remarks>
        /// {ClassName}/Cache调用  {ClassName}换成相应类型名称
        /// </remarks>
        /// <returns></returns>
        public void Cache(IWebSocketServerAction IWebSocketClass, SocketRequest Request)
        {
            if (!IWebSocketClass.CacheBeforeValidate(Request))
            {
                return;
            }
            ResponseResult responseResult = new ResponseResult
            {
                ClassName = Request.ClassName,
                ActionName = CacheName,
                Message = "缓存成功",
                Status = 101
            };
            if (!IWebSocketClass.SocketList.Contains(Request.Socket))
            {
                if (IWebSocketClass.SocketList.Count >= IWebSocketClass.CacheMaxCount)
                {
                    IWebSocketClass.ClearNotOnlineCache();
                    if (IWebSocketClass.SocketList.Count >= IWebSocketClass.CacheMaxCount)
                    {
                        ClearCache(IWebSocketClass, Request.ClassName);
                    }
                }
                var cache = Request.Socket.ConnectionInfo.Cookies[CacheName];
                if (!cache.Split(',').Contains(Request.ClassName))
                {
                    cache = cache.Length < 1 ? Request.ClassName : cache + "," + Request.ClassName;
                    Request.Socket.ConnectionInfo.Cookies[CacheName] = cache;
                }
                IWebSocketClass.SocketList.Add(Request.Socket);
            }
            else
            {
                responseResult.Message = "缓存已存在";
            }
            Request.Socket.Json(responseResult);
        }

        /// <summary>
        /// 清除当前缓存的客户端
        /// </summary>
        /// <param name="IWebSocketClass">请求到的类</param>
        /// <param name="ClassName">请求到的类型名</param>
        /// <returns></returns>
        public void ClearCache(IWebSocketServerAction IWebSocketClass, string ClassName)
        {
            IWebSocketClass.CacheClearBefore(ClassName);
            IWebSocketClass.SocketList.Clear();
            IWebSocketClass.CacheClearAfter(ClassName);

            ////更新Socket可用链接
            //IWebSocketClass.SocketList = IWebSocketClass.SocketList.Where(t => 
            //{
            //    if (!t.IsAvailable)
            //    {
            //        t.Json(responseResult);
            //    }
            //    return t.IsAvailable;
            //}).ToList();
            //if (IWebSocketClass.SocketList.Count >= IWebSocketClass.CacheMaxCount)
            //{
            //    IWebSocketClass.SocketList.ForEach(socket => socket.Json(responseResult));
            //    IWebSocketClass.SocketList.Clear();
            //}
        }
        #endregion

        #region 链接打开关闭时 进行处理
        /// <summary>
        /// Socket客户端链接时处理
        /// </summary>
        /// <param name="socket">客户端Socket</param>
        protected override void OnOpen(Fleck.IWebSocketConnection socket)
        {
            socket.ConnectionInfo.Cookies.Add(CacheName, "");
            base.OnOpen(socket);
        }

        /// <summary>
        /// Socket客户端断开时处理
        /// </summary>
        /// <param name="socket">客户端Socket</param>
        protected override void OnClose(Fleck.IWebSocketConnection socket)
        {
            var cache = socket.ConnectionInfo.Cookies[CacheName];
            bool IsCache = !string.IsNullOrEmpty(cache);
            if (string.IsNullOrEmpty(cache))
            {
                base.OnClose(socket);
                return;
            }
            //关闭缓存链接
            var ClassNameArray = cache.Split(',');

            foreach (var SocketClass in IWebSocketList.Where(t => ClassNameArray.Contains(t.Key)).Select(t => t.Value))
            {
                SocketClass.CloseAfter(socket);
                SocketClass.SocketList.Remove(socket);
            }
            base.OnClose(socket);
        }
        #endregion
    }
}
